#include "adas_muxbrd_fit.hh"

using namespace std;

int main(int argc, char *argv[])
{
    //-f
    string input_file_name;
    //-O
    string save_path_set = "fit_result";
    //-w
    bool is_write_waitalign_data = false;
    //-e
    bool is_write_event_json = false;
    //-U
    string user_set_layer_used = "ff";
    //-r
    float fit_rmse = 10;
    //-u
    bool is_have_target_det = false;
    //-v
    int target_det_idx = 0;
    //-a
    string alignment_filename = "alignmentbase.txt";
    //-y
    string rotate_filename = "rotatebase.txt";
    //-R
    string detector_hitrange_filename = "detector_hitrange.txt";
    //-g
    double eff_sigma = 3;
    //-L
    double ADC_LSB = 15;
    //-A
    bool is_fit_control_angle = false;
    //-G
    double angle_deg = 5;
    //-t
    bool is_aget = false;
    //-E
    bool is_region_eff = false;
    //-N
    int region_number = 4;

    while ((c = getopt(argc, argv, "f:O:wel:r:U:uv:a:y:g:L:R:AG:tEN:")) != -1)
    {
        switch (c)
        {
        case 'f':
            input_file_name = optarg;
            break;
        case 'O':
            save_path_set = optarg;
            break;
        case 'w':
            is_write_waitalign_data = true;
            break;
        case 'e':
            is_write_event_json = true;
            break;
        case 'r':
            fit_rmse = atof(optarg);
            break;
        case 'U':
            user_set_layer_used = optarg;
            break;
        case 'u':
            is_have_target_det = true;
            break;
        case 'v':
            target_det_idx = atoi(optarg);
            break;
        case 'a':
            alignment_filename = optarg;
            break;
        case 'y':
            rotate_filename = optarg;
            break;
        case 'g':
            eff_sigma = atof(optarg);
            break;
        case 'L':
            ADC_LSB = atof(optarg);
            break;
        case 'R':
            detector_hitrange_filename = optarg;
            break;
        case 'A':
            is_fit_control_angle = true;
            break;
        case 'G':
            angle_deg = atof(optarg);
            break;
        case 't':
            is_aget = true;
            break;
        case 'E':
            is_region_eff = true;
            break;
        case 'N':
            region_number = atoi(optarg);
            break;
        case '?':
            cout << cRED;
            cout << "<<---------------------->>" << endl;
            cout << "[Error]: unknow parameters" << endl;
            cout << "<<---------------------->>" << endl;
            cout << "Or forget break in the last case?" << endl;
            show_info(argv[0]);
            return -1;
        default:
            break;
        }
    }

    auto beforetime = chrono::system_clock::now();
    auto start = std::chrono::steady_clock::now();

    // 转换为时间戳（以秒为单位）
    auto new_timestamp = chrono::duration_cast<std::chrono::seconds>(beforetime.time_since_epoch()).count();

    // std::cout << "当前时间戳（秒）: " << new_timestamp << std::endl;

    if (is_aget)
    {
        ADC_LSB = 1;
    }
    else
    {
        ADC_LSB = ADC_LSB * 0.15492 * 2.048 * 0.001;
    }
    if (input_file_name.empty())
    {
        cout << cRED;
        cout << "<<---------------------->>" << endl;
        cout << "[Error]: input file name is empty" << endl;
        cout << "<<---------------------->>" << endl;
        show_info(argv[0]);
        return -1;
    }

    if (input_file_name.find(".root") == string::npos)
    {
        cout << cRED;
        cout << "<<---------------------->>" << endl;
        cout << "[Error]: file name is not correct" << endl;
        cout << "<<---------------------->>" << endl;
        show_info(argv[0]);
        return -1;
    }

    for (int i = 0; i < 20; i++)
    {
        cout << "==";
    }
    cout << endl;
    cout << "Begin process:" << endl;
    cout << endl;

    vector<string> file_name_path = split_string(input_file_name, "/");
    if (file_name_path.size() < 2)
    {
        file_name_path.push_back("default_path"); // 如果没有提供路径，则使用默认路径
    }

    if (is_write_event_json)
    {
        string relative_filename = file_name_path[0];
        vector<string> data_file_prefix = split_string(relative_filename, ".root");
        vector<string> idx = split_string(data_file_prefix[1], "_dec");
        vector<string> idx_event = split_string(idx[1], "-");
        string eventNumber = idx_event[0];
        eventNumber.erase(std::remove(eventNumber.begin(), eventNumber.end(), '-'), eventNumber.end());
        int event_number = stoi(eventNumber);
    }

    // std::time_t base_timestamp = 1715985120000;                                  // 基础时间戳
    // std::time_t new_timestamp = base_timestamp + (event_number - 9) * 60000 * 2; // 在基础时间戳上加上 event_number 分钟

    std::tm *ltm = std::localtime(&new_timestamp);
    std::stringstream ss;
    ss << new_timestamp;
    std::string time = ss.str();

    string save_path;
    string save_path_time;
    string save_path_event;
    string save_path_status;
    if (file_name_path[1].empty())
    {
        save_path = "./" + save_path_set;
        if (is_write_event_json)
        {
            save_path_time = "./" + save_path_set + "/" + time.c_str();
            save_path_event = "./" + save_path_set + "/" + time.c_str() + "/event";
            save_path_status = "./" + save_path_set + "/" + time.c_str() + "/status";
        }
    }
    else
    {
        save_path = file_name_path[1] + "/" + save_path_set;
        if (is_write_event_json)
        {
            save_path_time = file_name_path[1] + "/" + save_path_set + "/" + time.c_str();
            save_path_event = file_name_path[1] + "/" + save_path_set + "/" + time.c_str() + "/event";
            save_path_status = file_name_path[1] + "/" + save_path_set + "/" + time.c_str() + "/status";
        }
    }

    if (stat(save_path.c_str(), &info) == -1)
    {
        cout << cYELLOW << "Save path : " << save_path << " does not exist, create it." << cRESET << endl;
        fs::create_directories(save_path);
    }
    if (is_write_event_json)
    {
        if (stat(save_path_event.c_str(), &info) == -1)
        {
            // cout << cYELLOW << "Save path : " << save_path_event << " does not exist, create it." << cRESET << endl;
            fs::create_directories(save_path_event);
        }
        if (stat(save_path_time.c_str(), &info) == -1)
        {
            // cout << cYELLOW << "Save path : " << save_path_time << " does not exist, create it." << cRESET << endl;
            fs::create_directories(save_path_time);
        }
        if (stat(save_path_status.c_str(), &info) == -1)
        {
            // cout << cYELLOW << "Save path : " << save_path_status << " does not exist, create it." << cRESET << endl;
            fs::create_directories(save_path_status);
        }
    }
    string save_path_file = save_path + "/";

    int user_set_layer_used_int = 0;
    stringstream ss1;
    ss1 << hex << user_set_layer_used;
    ss1 >> user_set_layer_used_int;

    // fit pro
    fit_pro fit_pro(input_file_name, alignment_filename, rotate_filename, detector_hitrange_filename,  fit_rmse, is_have_target_det, target_det_idx, user_set_layer_used_int, eff_sigma, ADC_LSB, save_path_file, is_write_waitalign_data, is_write_event_json, is_fit_control_angle, angle_deg, save_path_time, is_region_eff, region_number);

    cout << cGREEN << "Done!" << cRESET << endl;

    // 使用 steady_clock 记录结束时间
    auto end = std::chrono::steady_clock::now();

    // 计算持续时间
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);

    std::cout << "持续时间: " << duration.count() << " 毫秒" << std::endl;

    return 0;
}

void show_info(char *name)
{
    cout << cCYAN;
    for (int i = 0; i < 15; i++)
    {
        cout << "==";
    }
    cout << endl
         << "Usage: " << name << " -[parameter] [options]" << endl
         << "Parameters:" << endl
         << "  -f [file name  xxx.root] : input file name (require)" << endl
         << "  -O [file name] : output file name (default: fit_result)" << endl
         << "  -w : write wait align data (default: false)" << endl
         << "  -e : write event json (default: false)" << endl
         << "  -l [int] : layer number (default: 6)" << endl
         << "  -r [float] : fit rmse (default: 10)" << endl
         << "  -U [string] : user set layer used (default: ff)" << endl
         << "  -u : have target det (default: false)" << endl
         << "  -v [int] : target det idx (default: 0)" << endl
         << "  -a [file name] : alignment file name (default: alignmentbase.txt)" << endl
         << "  -y [file name] : rotate file name (default: rotatebase.txt)" << endl
         << "  -g [float] : eff sigma (default: 3)" << endl
         << "  -L [float] : ADC LSB (default: 15)" << endl
         << "  -R [file name] : detector hitrange file name (default: detector_hitrange.txt)" << endl
         << "  -A : fit control angle (default: false)" << endl
         << "  -G [float] : angle deg (default: 5)" << endl
         << "  -t : AGET electronics (default: false)" << endl
         << "  -E : region efficiency (default: false)" << endl
         << "  -N [int] : region number (default: 4)" << endl
         << "if just want to run the layer track and obtain the alignment data: "
            "./adas_muxbrd_fit -f [file name] -l [layer_used] -U [user_set_layer_used] -r 10 -w "
         << endl
         << "if want to run the layer track and obtain the alignment data and event json: "
            "./adas_muxbrd_fit -f [file name] -l [layer_used] -U [user_set_layer_used] -r 10 -w -e"
         << endl
         << "if want to run the target layer detector performance: "
            "./adas_muxbrd_fit -f [file name] -l [layer_used] -U [user_set_layer_used] -u -v [target_det_idx] -r 1 -a [alignment_file] -y [rotate_file] -g [eff_sigma]"
         << endl

         << cRESET << endl;
}

vector<string> split_string(const string &str, string delims, int inc)
{
    std::vector<std::string> result;
    size_t i = str.rfind(delims, str.length());
    if (i == str.length() - 1 || i == string::npos)
    {
        result.push_back(str);
    }
    else
    {
        result.push_back(str.substr(i + inc, str.length() - i));
        result.push_back(str.substr(0, i));
    }
    return result;
}
